/*
    cJSONX.h
*/

#ifndef cJSONX__h
#define cJSONX__h

#ifndef cJSON__h
 #include "cJSON.h"
#endif

#ifdef __cplusplus
extern "C"
{
#endif

/*
 * cjx
 */
#define CJX_GET_ERR()       (cJSON_GetErrorPtr())
#define CJX_NEW_OBJ()       (cJSON_CreateObject())
#define CJX_END_OBJ(_OBJ)   (cJSON_Delete(_OBJ))

//val
#define CJX_OBJ2STR(_OBJ)   ((cJSON_IsString(_OBJ)) ? _OBJ->valuestring : "")
#define CJX_OBJ2INT(_OBJ)   ((cJSON_IsNumber(_OBJ)) ? _OBJ->valueint : 0)

#define CJX_STR2OBJ(_STR)   (cJSON_CreateString(_STR))
#define CJX_INT2OBJ(_INT)   (cJSON_CreateNumber(_INT))

//obj
#define CJX_SET_OBJ(_ROOT, _KEY, _OBJ) \
{ \
    cJSON *__obj = NULL; \
    __obj = _OBJ; \
    if(!cJSON_IsInvalid(__obj)) \
    { \
        if(cJSON_HasObjectItem(_ROOT, _KEY)) \
            cJSON_ReplaceItemInObject(_ROOT, _KEY, __obj); \
        else \
            cJSON_AddItemToObject(_ROOT, _KEY, __obj); \
    } \
}

#define CJX_GET_OBJ(_ROOT, _KEY, _OBJ) \
{ \
    cJSON *__obj = NULL; \
    __obj = cJSON_GetObjectItem(_ROOT, _KEY); \
    if(!cJSON_IsInvalid(__obj)) \
        _OBJ = __obj; \
}

#define CJX_DEL_OBJ(_ROOT, _KEY)    cJSON_DeleteItemFromObject(_ROOT, _KEY)

//num
#define CJX_SET_NUM(_ROOT, _KEY, _NUM) \
{ \
    cJSON *__obj = NULL; \
    __obj = CJX_INT2OBJ(_NUM); \
    if(!cJSON_IsInvalid(__obj)) \
    { \
        if(cJSON_HasObjectItem(_ROOT, _KEY)) \
            cJSON_ReplaceItemInObject(_ROOT, _KEY, __obj); \
        else \
            cJSON_AddItemToObject(_ROOT, _KEY, __obj); \
    } \
}

#define CJX_GET_NUM(_ROOT, _KEY, _NUM) \
{ \
    cJSON *__obj = NULL; \
    __obj = cJSON_GetObjectItem(_ROOT, _KEY); \
    if(!cJSON_IsInvalid(__obj)) \
        _NUM = CJX_OBJ2INT(__obj); \
}

#define CJX_DEL_NUM(_ROOT, _KEY)    cJSON_DeleteItemFromObject(_ROOT, _KEY)

//str
#define CJX_SET_STR(_ROOT, _KEY, _STR) \
{ \
    cJSON *__obj = NULL; \
    __obj = CJX_STR2OBJ(_STR); \
    if(!cJSON_IsInvalid(__obj)) \
    { \
        if(cJSON_HasObjectItem(_ROOT, _KEY)) \
            cJSON_ReplaceItemInObject(_ROOT, _KEY, __obj); \
        else \
            cJSON_AddItemToObject(_ROOT, _KEY, __obj); \
    } \
}

#define CJX_GET_STR(_ROOT, _KEY, _STR) \
{ \
    cJSON *__obj = NULL; \
    __obj = cJSON_GetObjectItem(_ROOT, _KEY); \
    if(!cJSON_IsInvalid(__obj)) \
        strcpy(_STR, CJX_OBJ2STR(__obj)); \
}

#define CJX_DEL_STR(_ROOT, _KEY)    cJSON_DeleteItemFromObject(_ROOT, _KEY)

//array
#define CJX_SET_ARRAY(_ROOT, _KEY, _OBJ) \
{ \
    cJSON *__obj = NULL; \
    __obj = cJSON_GetObjectItem(_ROOT, _KEY); \
    if(NULL == __obj) \
    { \
        __obj = cJSON_CreateArray(); \
        cJSON_AddItemToObject(_ROOT, _KEY, __obj); \
    } \
    if(cJSON_IsArray(__obj)) \
        cJSON_AddItemToArray(__obj, _OBJ); \
}

#define CJX_SET_ARRAY_NUM(_ROOT, _KEY, _NUM)    CJX_SET_ARRAY(_ROOT, _KEY, CJX_INT2OBJ(_NUM))
#define CJX_SET_ARRAY_STR(_ROOT, _KEY, _STR)    CJX_SET_ARRAY(_ROOT, _KEY, CJX_STR2OBJ(_STR))

#define CJX_GET_ARRAY_IDX(_ROOT, _KEY, _IDX, _OBJ) \
{ \
    cJSON *__obj = NULL; \
    __obj = cJSON_GetObjectItem(_ROOT, _KEY); \
    if(cJSON_IsArray(__obj) && (_IDX < cJSON_GetArraySize(__obj))) \
        _OBJ = cJSON_GetArrayItem(__obj, _IDX); \
}

#define CJX_GET_ARRAY_NUM_IDX(_ROOT, _KEY, _IDX, _NUM) \
{ \
    cJSON *__obj2 = NULL; \
    CJX_GET_ARRAY_IDX(_ROOT, _KEY, _IDX, __obj2); \
    if(!cJSON_IsInvalid(__obj2)) \
        _NUM = CJX_OBJ2INT(__obj2); \
}

#define CJX_GET_ARRAY_STR_IDX(_ROOT, _KEY, _IDX, _STR) \
{ \
    cJSON *__obj2 = NULL; \
    CJX_GET_ARRAY_IDX(_ROOT, _KEY, _IDX, __obj2); \
    if(!cJSON_IsInvalid(__obj2)) \
        strcpy(_STR, CJX_OBJ2STR(__obj2)); \
}

#define CJX_GET_ARRAY_SIZE(_ROOT, _KEY, _SIZE) \
{ \
    cJSON *__obj = NULL; \
    __obj = cJSON_GetObjectItem(_ROOT, _KEY); \
    if(cJSON_IsArray(__obj)) \
        _SIZE = cJSON_GetArraySize(__obj); \
}

#define CJX_GET_ARRAY_FOR(_ROOT, _KEY, _OBJ) \
    if (cJSON_IsArray(cJSON_GetObjectItem(_ROOT, _KEY))) \
        cJSON_ArrayForEach(_OBJ, cJSON_GetObjectItem(_ROOT, _KEY))

#define CJX_DEL_ARRAY(_ROOT, _KEY)    cJSON_DeleteItemFromObject(_ROOT, _KEY)

#ifdef __cplusplus
}
#endif

#endif
